"""题目存储服务 - Redis持久化存储"""
from typing import List, Dict, Any, Optional
import json
from app.core.database import RedisClient


class QuestionStorageService:
    """题目存储服务 - 负责题目的Redis存储和读取"""
    
    def __init__(self):
        try:
            self.redis = RedisClient.get_client()
            self.redis.ping()
        except Exception as e:
            print(f"警告: Redis连接失败，将使用内存存储: {e}")
            self.redis = None
    
    def add_questions(self, questions: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        批量添加题目到Redis
        
        Args:
            questions: 题目列表
            
        Returns:
            添加结果统计
        """
        if not questions:
            return {"added": 0, "skipped": 0, "errors": []}
        
        added_count = 0
        skipped_count = 0
        errors = []
        
        if self.redis:
            try:
                # 使用pipeline批量操作
                pipe = self.redis.pipeline()
                
                for question in questions:
                    try:
                        question_id = question.get("question_id")
                        if not question_id:
                            errors.append("题目缺少question_id字段")
                            continue
                        
                        # 检查题目是否已存在
                        question_key = f"question:{question_id}"
                        if self.redis.exists(question_key):
                            skipped_count += 1
                            continue
                        
                        # 存储题目数据（使用Hash存储）
                        question_data = json.dumps(question, ensure_ascii=False)
                        pipe.hset(question_key, mapping={
                            "data": question_data,
                            "question_id": question_id,
                            "subject": question.get("subject", ""),
                            "category": question.get("category", ""),
                            "year": str(question.get("year", "")),
                            "source": question.get("source", "manual"),
                            "difficulty": question.get("difficulty", "medium"),
                            "type": question.get("type", "single_choice"),
                            "exam_type": question.get("exam_type", ""),  # 考试类型：客观一/客观二/主观题
                            "exam_label": question.get("exam_label", "")  # 考试标签
                        })
                        
                        # 添加到索引集合
                        pipe.sadd("question_ids:all", question_id)
                        
                        # 按科目索引
                        subject = question.get("subject", "unknown")
                        pipe.sadd(f"question_ids:by_subject:{subject}", question_id)
                        
                        # 按年份索引
                        year = question.get("year")
                        if year:
                            pipe.sadd(f"question_ids:by_year:{year}", question_id)
                        
                        # 按类别索引
                        category = question.get("category", "")
                        if category:
                            pipe.sadd(f"question_ids:by_category:{category}", question_id)
                        
                        # 按考试类型索引
                        exam_type = question.get("exam_type", "")
                        if exam_type:
                            pipe.sadd(f"question_ids:by_exam_type:{exam_type}", question_id)
                        
                        added_count += 1
                    except Exception as e:
                        errors.append(f"题目 {question.get('question_id', 'unknown')} 处理失败: {str(e)}")
                
                # 执行批量操作
                pipe.execute()
                
                # 更新统计信息
                self._update_stats()
                
                print(f"✅ 成功添加 {added_count} 道题目到Redis，跳过 {skipped_count} 道重复题目")
            except Exception as e:
                errors.append(f"Redis批量操作失败: {str(e)}")
                print(f"❌ 添加题目到Redis失败: {e}")
        else:
            errors.append("Redis不可用，无法存储题目")
        
        return {
            "added": added_count,
            "skipped": skipped_count,
            "errors": errors
        }
    
    def get_question_by_id(self, question_id: str) -> Optional[Dict[str, Any]]:
        """根据ID获取题目"""
        if not self.redis:
            return None
        
        try:
            question_key = f"question:{question_id}"
            if not self.redis.exists(question_key):
                return None
            
            question_data = self.redis.hget(question_key, "data")
            if question_data:
                return json.loads(question_data)
        except Exception as e:
            print(f"从Redis获取题目失败: {e}")
        
        return None
    
    def get_questions_by_subject(self, subject: str) -> List[Dict[str, Any]]:
        """根据科目获取题目列表"""
        if not self.redis:
            return []
        
        try:
            question_ids = self.redis.smembers(f"question_ids:by_subject:{subject}")
            questions = []
            for qid in question_ids:
                if isinstance(qid, bytes):
                    qid = qid.decode('utf-8')
                question = self.get_question_by_id(qid)
                if question:
                    questions.append(question)
            return questions
        except Exception as e:
            print(f"从Redis获取科目题目失败: {e}")
            return []
    
    def get_questions_by_year(self, year: int) -> List[Dict[str, Any]]:
        """根据年份获取题目列表"""
        if not self.redis:
            return []
        
        try:
            question_ids = self.redis.smembers(f"question_ids:by_year:{year}")
            questions = []
            for qid in question_ids:
                if isinstance(qid, bytes):
                    qid = qid.decode('utf-8')
                question = self.get_question_by_id(qid)
                if question:
                    questions.append(question)
            return questions
        except Exception as e:
            print(f"从Redis获取年份题目失败: {e}")
            return []
    
    def get_all_question_ids(self) -> List[str]:
        """获取所有题目ID"""
        if not self.redis:
            return []
        
        try:
            question_ids = self.redis.smembers("question_ids:all")
            return [qid.decode('utf-8') if isinstance(qid, bytes) else qid for qid in question_ids]
        except Exception as e:
            print(f"从Redis获取所有题目ID失败: {e}")
            return []
    
    def get_all_questions(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
        """获取所有题目（支持限制数量）"""
        question_ids = self.get_all_question_ids()
        
        if limit:
            question_ids = question_ids[:limit]
        
        questions = []
        for qid in question_ids:
            question = self.get_question_by_id(qid)
            if question:
                questions.append(question)
        
        return questions
    
    def get_question_count(self) -> Dict[str, Any]:
        """获取题目统计信息"""
        if not self.redis:
            return {"total": 0, "by_subject": {}, "by_year": {}}
        
        try:
            total = self.redis.scard("question_ids:all")
            
            # 按科目统计
            by_subject = {}
            subjects = ["civil_law", "civil_procedure", "criminal_law", "criminal_procedure",
                       "administrative", "commercial", "international", "comprehensive"]
            for subject in subjects:
                count = self.redis.scard(f"question_ids:by_subject:{subject}")
                if count > 0:
                    by_subject[subject] = count
            
            # 按年份统计
            by_year = {}
            current_year = 2025
            for year in range(current_year - 4, current_year + 1):
                count = self.redis.scard(f"question_ids:by_year:{year}")
                if count > 0:
                    by_year[year] = count
            
            return {
                "total": total,
                "by_subject": by_subject,
                "by_year": by_year
            }
        except Exception as e:
            print(f"获取题目统计失败: {e}")
            return {"total": 0, "by_subject": {}, "by_year": {}}
    
    def _update_stats(self):
        """更新统计信息"""
        if not self.redis:
            return
        
        try:
            stats = self.get_question_count()
            stats_key = "question_stats:summary"
            self.redis.set(stats_key, json.dumps(stats, ensure_ascii=False))
        except Exception as e:
            print(f"更新统计信息失败: {e}")
    
    def delete_question(self, question_id: str) -> bool:
        """删除题目"""
        if not self.redis:
            return False
        
        try:
            question_key = f"question:{question_id}"
            if not self.redis.exists(question_key):
                return False
            
            # 获取题目信息（用于删除索引）
            question = self.get_question_by_id(question_id)
            if not question:
                return False
            
            # 删除题目数据
            self.redis.delete(question_key)
            
            # 从索引中删除
            self.redis.srem("question_ids:all", question_id)
            
            subject = question.get("subject", "")
            if subject:
                self.redis.srem(f"question_ids:by_subject:{subject}", question_id)
            
            year = question.get("year")
            if year:
                self.redis.srem(f"question_ids:by_year:{year}", question_id)
            
            category = question.get("category", "")
            if category:
                self.redis.srem(f"question_ids:by_category:{category}", question_id)
            
            # 更新统计
            self._update_stats()
            
            return True
        except Exception as e:
            print(f"删除题目失败: {e}")
            return False
    
    def migrate_from_memory(self, question_bank: List[Dict[str, Any]]) -> Dict[str, Any]:
        """将内存中的题库迁移到Redis"""
        print(f"开始迁移 {len(question_bank)} 道题目到Redis...")
        result = self.add_questions(question_bank)
        print(f"迁移完成: 添加 {result['added']} 道，跳过 {result['skipped']} 道")
        return result


# 单例实例
    def add_temporary_questions(
        self,
        questions: List[Dict[str, Any]],
        expire_days: int = 7
    ) -> Dict[str, Any]:
        """
        添加临时题目（有效期7天）
        
        Args:
            questions: 题目列表
            expire_days: 过期天数，默认7天
            
        Returns:
            添加结果统计
        """
        if not questions:
            return {"added": 0, "skipped": 0, "errors": []}
        
        added_count = 0
        skipped_count = 0
        errors = []
        
        if self.redis:
            try:
                pipe = self.redis.pipeline()
                expire_seconds = expire_days * 86400
                
                for question in questions:
                    try:
                        question_id = question.get("question_id")
                        if not question_id:
                            errors.append("题目缺少question_id字段")
                            continue
                        
                        # 存储到临时题目集合
                        temp_question_key = f"temp_question:{question_id}"
                        question_data = json.dumps(question, ensure_ascii=False)
                        pipe.hset(temp_question_key, mapping={
                            "data": question_data,
                            "question_id": question_id,
                            "subject": question.get("subject", ""),
                            "category": question.get("category", ""),
                            "generated_by": question.get("generated_by", "LLM"),
                            "generated_at": question.get("generated_at", ""),
                            "source": "llm_generated"
                        })
                        pipe.expire(temp_question_key, expire_seconds)
                        
                        # 添加到临时题目索引
                        pipe.sadd("temp_question_ids:all", question_id)
                        pipe.expire("temp_question_ids:all", expire_seconds)
                        
                        # 按科目索引
                        subject = question.get("subject", "unknown")
                        pipe.sadd(f"temp_question_ids:by_subject:{subject}", question_id)
                        pipe.expire(f"temp_question_ids:by_subject:{subject}", expire_seconds)
                        
                        added_count += 1
                    except Exception as e:
                        errors.append(f"题目 {question.get('question_id', 'unknown')} 处理失败: {str(e)}")
                
                pipe.execute()
                print(f"✅ 成功添加 {added_count} 道临时题目到Redis（有效期{expire_days}天）")
            except Exception as e:
                print(f"⚠️ 添加临时题目到Redis失败: {e}")
        
        # 如果Redis不可用，使用文件存储
        if not self.redis or added_count == 0:
            try:
                from app.services.file_storage_service import file_storage_service
                for question in questions:
                    question_id = question.get("question_id")
                    if question_id:
                        file_key = f"temp_question:{question_id}"
                        file_storage_service.save_data(file_key, question)
                        added_count += 1
                print(f"✅ 成功添加 {added_count} 道临时题目到文件存储")
            except Exception as e:
                print(f"⚠️ 添加临时题目到文件存储失败: {e}")
        
        return {
            "added": added_count,
            "skipped": skipped_count,
            "errors": errors
        }
    
    def get_temporary_question(self, question_id: str) -> Optional[Dict[str, Any]]:
        """
        获取临时题目
        
        Args:
            question_id: 题目ID
            
        Returns:
            题目字典，如果不存在返回None
        """
        if self.redis:
            try:
                temp_question_key = f"temp_question:{question_id}"
                if self.redis.exists(temp_question_key):
                    question_data = self.redis.hget(temp_question_key, "data")
                    if question_data:
                        return json.loads(question_data)
            except Exception as e:
                print(f"⚠️ 从Redis获取临时题目失败: {e}")
        
        # 如果Redis没有，尝试文件存储
        try:
            from app.services.file_storage_service import file_storage_service
            file_key = f"temp_question:{question_id}"
            question = file_storage_service.load_data(file_key)
            if question:
                return question
        except Exception as e:
            print(f"⚠️ 从文件存储获取临时题目失败: {e}")
        
        return None
    
    def get_all_temporary_questions(self) -> List[Dict[str, Any]]:
        """获取所有临时题目"""
        questions = []
        
        if self.redis:
            try:
                question_ids = self.redis.smembers("temp_question_ids:all") or []
                for qid in question_ids:
                    if isinstance(qid, bytes):
                        qid = qid.decode('utf-8')
                    question = self.get_temporary_question(qid)
                    if question:
                        questions.append(question)
            except Exception as e:
                print(f"⚠️ 从Redis获取所有临时题目失败: {e}")
        
        # 如果Redis没有，尝试文件存储
        if not questions:
            try:
                from app.services.file_storage_service import file_storage_service
                # 扫描临时题目文件
                import os
                from pathlib import Path
                storage_dir = file_storage_service.storage_dir
                pattern = "temp_question_*.json"
                for file_path in storage_dir.glob(pattern):
                    try:
                        question = file_storage_service.load_data(file_path.stem.replace("_", ":"))
                        if question:
                            questions.append(question)
                    except:
                        pass
            except Exception as e:
                print(f"⚠️ 从文件存储获取所有临时题目失败: {e}")
        
        return questions


question_storage_service = QuestionStorageService()

